agentmux_srv\backend\lsp/
workspace.rs1use std::path::{Path, PathBuf};
10
11const MARKERS: &[&str] = &[
15 ".git",
16 "Cargo.toml",
17 "package.json",
18 "go.mod",
19 "pyproject.toml",
20 "deno.json",
21 "deno.jsonc",
22 "tsconfig.json",
23];
24
25pub fn detect_workspace_root(file_path: &Path) -> PathBuf {
26 let mut current = file_path.parent();
27 while let Some(dir) = current {
28 for marker in MARKERS {
29 if dir.join(marker).exists() {
30 return dir.to_path_buf();
31 }
32 }
33 current = dir.parent();
34 }
35 file_path
37 .parent()
38 .unwrap_or_else(|| Path::new("."))
39 .to_path_buf()
40}
41
42#[cfg(test)]
43mod tests {
44 use super::*;
45 use std::fs;
46
47 #[test]
48 fn falls_back_to_parent_dir_when_no_marker() {
49 let tmp = tempfile::tempdir().unwrap();
50 let file = tmp.path().join("loose.txt");
51 fs::write(&file, "").unwrap();
52 assert_eq!(detect_workspace_root(&file), tmp.path());
54 }
55
56 #[test]
57 fn finds_git_root_up_the_tree() {
58 let tmp = tempfile::tempdir().unwrap();
59 let root = tmp.path();
60 fs::create_dir(root.join(".git")).unwrap();
61 let sub = root.join("a/b/c");
62 fs::create_dir_all(&sub).unwrap();
63 let file = sub.join("file.rs");
64 fs::write(&file, "").unwrap();
65 assert_eq!(detect_workspace_root(&file), root);
66 }
67
68 #[test]
69 fn finds_cargo_root() {
70 let tmp = tempfile::tempdir().unwrap();
71 let root = tmp.path();
72 fs::write(root.join("Cargo.toml"), "").unwrap();
73 let sub = root.join("src");
74 fs::create_dir(&sub).unwrap();
75 let file = sub.join("main.rs");
76 fs::write(&file, "").unwrap();
77 assert_eq!(detect_workspace_root(&file), root);
78 }
79
80 #[test]
81 fn closest_ancestor_wins_when_nested_markers() {
82 let tmp = tempfile::tempdir().unwrap();
85 let outer = tmp.path();
86 fs::write(outer.join("Cargo.toml"), "").unwrap();
87 let inner = outer.join("frontend");
88 fs::create_dir(&inner).unwrap();
89 fs::write(inner.join("package.json"), "").unwrap();
90 let file = inner.join("src/index.ts");
91 fs::create_dir(inner.join("src")).unwrap();
92 fs::write(&file, "").unwrap();
93 assert_eq!(detect_workspace_root(&file), inner);
94 }
95}